package main

import (
	"basic-go/src/go-routine/util"
	"fmt"
	"runtime"
	"time"
)

// 使用协程统计1-20000里面的素数。
// 启动4个协程来处理，最后在主线程或一个单独的协程输出结果。

var countDownLatch *util.CountDownLatch

func putNumber(intChan chan<- int, count int) {
	for i := 1; i <= count; i++ {
		intChan <- i
	}
	close(intChan)
}

func compute(intChan <-chan int, resultChan chan<- int) {
	for num := range intChan {
		isPrime := true
		for i := 2; i <= num-1; i++ {
			if num%i == 0 {
				isPrime = false
			}
		}
		if isPrime {
			resultChan <- num
		}
	}
	countDownLatch.CountDown()
}

func main() {

	start := time.Now().UnixNano()

	// 单线程模式效率
	singleThread()

	// 多协程模式效率
	//multiGoRoutine()

	fmt.Println(float64(time.Now().UnixNano()-start) / float64(1000000))
}

func singleThread() {

	var intChan = make(chan int, 20000)
	var resultChan = make(chan int, 20000)

	// 生成数据
	go putNumber(intChan, 20000)

	// 计算
	for num := range intChan {
		isPrime := true
		for i := 2; i <= num-1; i++ {
			if num%i == 0 {
				isPrime = false
			}
		}
		if isPrime {
			resultChan <- num
		}
	}
	close(resultChan)

	// 遍历结果
	for res := range resultChan {
		fmt.Println(res)
	}
}

func multiGoRoutine() {

	numCPU := runtime.NumCPU()

	var intChan = make(chan int, 20000)
	var resultChan = make(chan int, 20000)

	// 生成数据
	go putNumber(intChan, 20000)

	// 启动计算协程
	countDownLatch = util.NewCountDownLatch(numCPU)
	for i := 1; i <= numCPU; i++ {
		go compute(intChan, resultChan)
	}

	// 异步关闭resultChan
	go func() {
		countDownLatch.Await()
		close(resultChan)
	}()

	// 遍历结果
	for res := range resultChan {
		fmt.Println(res)
	}
}
